package com.dp1.deliversoft.entidad;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import com.dp1.deliversoft.algorithm.Calculos;

public class TablaRuteoAux {
	private Hashtable<Integer, Hashtable<Integer, CeldaAux>> tbRuteo;
	private double coeficienteEvaporacion = 0.5;

	public TablaRuteoAux(ArrayList<Pedido> pedidos, Mapa mapa) {
		Hashtable<Integer, CeldaAux> tbSubRuteo;
		CeldaAux celda;
		tbRuteo = new Hashtable<Integer, Hashtable<Integer, CeldaAux>>();
		Integer claveP = 0;
		Integer claveS = 0;
		int coord_x = 0, coord_y = 0,coord_dx = 0, coord_dy = 0, cantKms = 0;
		double visi = 0.0;
		int pedido_actual = -1; // es el almacen, q no es un pedido
		int pedido_siguiente = -1; // la primera "siguiente casa" es la primera
									// casa del arreglo de pedidos
		int cant = pedidos.size() + 1; // Le estoy sumando el lugar del almacen

		for (int i = 0; i < cant; i++) {
			claveP = new Integer(i);
			tbSubRuteo = new Hashtable<Integer, CeldaAux>();

			if (i == 0) {
				// Esta en el almacen, por tanto no considero coordenadas del
				// pedido sino las coordenadas del almacen
				coord_x = mapa.getUbicacionAlmacen().getX();
				coord_y = mapa.getUbicacionAlmacen().getY();
				pedido_actual = -1; // el almacen
			} else {
				// Saca las coordenadas actuales del lugar donde esta
				pedido_actual++;
				coord_x = pedidos.get(pedido_actual).getPosX();
				coord_y = pedidos.get(pedido_actual).getPosY();

			}
			
			for (int j = 0; j < cant; j++) {
				claveS = new Integer(j);

				if (j == 0) {
					// Esta en el almacen, por tanto no considero coordenadas del
					// pedido sino las coordenadas del almacen
					coord_dx = mapa.getUbicacionAlmacen().getX();
					coord_dy = mapa.getUbicacionAlmacen().getY();
					pedido_siguiente = -1; // el almacen
				} else {
					// Saca las coordenadas actuales del lugar donde esta
					pedido_siguiente++;
					coord_dx = pedidos.get(pedido_siguiente).getPosX();
					coord_dy = pedidos.get(pedido_siguiente).getPosY();

				}
				cantKms = Calculos.CalcDistanciaEnKm(coord_x, coord_y, coord_dx,
						coord_dy);
				visi = 1.0 / (double) cantKms;

				celda = new CeldaAux(pedido_actual, pedido_siguiente, 0,
						cantKms, visi, Math.pow(visi,
								Constantes.HormigasBetaDist));
				// graba la posicion en el arreglo de pedidos
				// de ambos locales, y la visibilidad

				tbSubRuteo.put(claveS, celda);
				tbRuteo.put(claveP, tbSubRuteo);
			}
			
			pedido_siguiente = -1;
		}
		
	}

	public void dibujar(ArrayList<Pedido> pedidos) {
		Enumeration<Integer> e = tbRuteo.keys();
		Integer clave;
		Hashtable<Integer, CeldaAux> tbSubRuteo;

		Enumeration<Integer> e2;
		Integer clave2;
		CeldaAux celda;

		while (e.hasMoreElements()) {
			clave = e.nextElement();
			tbSubRuteo = tbRuteo.get(clave);
			
			e2 = tbSubRuteo.keys();
			System.out.print(clave+" _ ");
			while (e2.hasMoreElements()) {
				clave2 = e2.nextElement();
				celda = tbSubRuteo.get(clave2);
				//if (celda.getPosA_ArregloPedidos() != -1) {
					System.out.print(//Calculos.Redondear(celda.getFeromonas(),3)+" "
							//pedidos.get(celda.getPosA_ArregloPedidos()).getPosX()
							clave2
							);

				//}
			}
			System.out.println();
		}
	}

	public Hashtable<Integer, Hashtable<Integer, CeldaAux>> getTbRuteo() {
		return tbRuteo;
	}

	public void setTbRuteo(
			Hashtable<Integer, Hashtable<Integer, CeldaAux>> tbRuteo) {
		this.tbRuteo = tbRuteo;
	}

	/*public void actualizarFeromona(int pos1, int pos2, Ruta s) {
		Hashtable<Integer, CeldaAux> tbSubRuteo;
		CeldaAux celda;

		tbSubRuteo = tbRuteo.get(pos1);
		celda = tbSubRuteo.get(pos2);
		celda.setFeromonas((double) (celda.getFeromonas() + ((double) ( (double) s
				.getCostoRuta()))));

	}*/

	public void actualizarFeromonaSinConActualizar(int pos1, int pos2, Ruta s, boolean act, Ruta SF) {
		Hashtable<Integer, CeldaAux> tbSubRuteo;
		CeldaAux celda;
		double c=0, formula=0;
		
		tbSubRuteo = tbRuteo.get(pos1);
		celda = tbSubRuteo.get(pos2);
		double factor = 1;
		
		//c = celda.getCantKms();
		//formula = (s.getCostoRuta()+1)/((c/s.getCostoRuta()) + s.getCostoRuta());
		formula = 100/celda.getCantKms();
		if (SF.getCostoRuta()>s.getCostoRuta())
		{
			factor = 1;
		}
		else
		{
			factor = 1;
		}
		//formula = 1/s.getCostoRuta();//(s.getCostoRuta()+1)/((c/s.getCostoRuta()) + s.getCostoRuta());
		
		if (act)
		{
			//actualiza defrente las feromonas
			//formula = ( (double) s.getCostoRuta());
			celda.setFeromonas((double) (celda.getFeromonas() + formula*factor));
		}
		else if(!act)
		{
			//guarda en las feromonas sin actualizar aun
			//formula = ( (double) s.getCostoRuta());
			celda.setFeromonasSinActualizar((double) (celda.getFeromonasSinActualizar() + formula*factor));
		}
	
	}

	public void ActualizarCambiosFeromonas() {
		// TODO Auto-generated method stub
		Enumeration<Integer> e = tbRuteo.keys();
		Integer clave;
		Hashtable<Integer, CeldaAux> tbSubRuteo;

		Enumeration<Integer> e2;
		Integer clave2;
		CeldaAux celda;

		while (e.hasMoreElements()) {
			clave = e.nextElement();
			tbSubRuteo = tbRuteo.get(clave);

			e2 = tbSubRuteo.keys();

			while (e2.hasMoreElements()) {
				clave2 = e2.nextElement();
				celda = tbSubRuteo.get(clave2);

				celda.setFeromonas((double) (celda.getFeromonas() + celda
						.getFeromonasSinActualizar()));
				celda.setFeromonasSinActualizar(0);

			}
		}
	}

	public void EvaporarFeromonas() {
		// TODO Auto-generated method stub
		Enumeration<Integer> e = tbRuteo.keys();
		Integer clave;
		Hashtable<Integer, CeldaAux> tbSubRuteo;

		Enumeration<Integer> e2;
		Integer clave2;
		CeldaAux celda;

		while (e.hasMoreElements()) {
			clave = e.nextElement();
			tbSubRuteo = tbRuteo.get(clave);

			e2 = tbSubRuteo.keys();

			while (e2.hasMoreElements()) {
				clave2 = e2.nextElement();
				celda = tbSubRuteo.get(clave2);

				celda.setFeromonas((double) (celda.getFeromonas() * coeficienteEvaporacion));

			}
		}
	}

}
